package ui;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
//import java.awt.font.TextAttribute;
//import java.util.Map;

import javax.swing.*;

/**
 * This implementation of a font chooser panel gives the ability to select
 * font family, size, bold and italics. The selected font is returned as
 * a Font object. Additionally, a preview component can be added to the
 * font chooser. If a preview component is added, it will be notified
 * through its setFont method whenever the font changes.
 * 
 * @author john
 *
 */
public class FontChooser extends JPanel implements ActionListener {

	private Font selectedFont = null;
	private JComboBox fontBox, sizeBox;
	private JToggleButton boldBtn, italicBtn; // underlineBtn;
	private Component preview;
	
	/**
	 * Creates a font chooser displaying all available fonts.
	 *
	 */
	public FontChooser() {
		setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
		initComponents();
		setVisible(true);
	}
	
	/**
	 * Returns the currently selected font, or null if no selection
	 * was made.
	 * @param fonts		currently selected font
	 */
	public Font getSelectedFont() {
		return selectedFont;
	}
	
	/**
	 * Sets the preview component. This component's setFont method
	 * is called every time the font changes. Setting it to null
	 * un-registers the previously set preview component.
	 * @param c		preview component
	 */
	public void setPreview(Component c) {
		preview = c;
		if (c != null)
			c.setFont(selectedFont);
	}
	
	/**
	 * Tries to set the selected font to the given font.
	 * Does nothing if the name does not match a valid font. 
	 * @param f		new font
	 */
	public void setSelectedFont(Font f) {
		fontBox.setSelectedItem(f.getFamily());
		sizeBox.setSelectedItem(Integer.toString(f.getSize()));
		setBold(f.isBold());
		setItalic(f.isItalic());
//		setUnderline(f.getAttributes().get(TextAttribute.UNDERLINE) == TextAttribute.UNDERLINE_ON);
	}
	
	/**
	 * Tries to set the selected font to the specified font name.
	 * Does nothing if the name does not match a valid font.
	 * @param str	font name
	 */
	public void setSelectedFont(String str) {
		fontBox.setSelectedItem(str);
	}
	
	/**
	 * Sets the font size.
	 * @param str	font size
	 */
	public void setSelectedFontSize(String str) {
		sizeBox.setSelectedItem(str);
	}
	
	/**
	 * Sets the bold state.
	 * @param b	
	 */
	public void setBold(boolean b) {
		boldBtn.setSelected(!b);
		boldBtn.doClick();
	}
	
	/**
	 * Sets the italic state.
	 * @param b
	 */
	public void setItalic(boolean b) {
		italicBtn.setSelected(!b);
		italicBtn.doClick();
	}
	
//	/**
//	 * Sets the underline state.
//	 * @param b
//	 */
//	public void setUnderline(boolean b) {
//		underlineBtn.setSelected(!b);
//		underlineBtn.doClick();
//	}
	
	private static String[] fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); 
	
	private void initComponents() {
		fontBox = new JComboBox(fontNames);
		fontBox.addActionListener(this);
		add(fontBox);
		
		String[] sizes = {"6", "8", "10", "12", "14", "16", "18", "20", "24", "28",
				"32", "36", "40", "44", "48", "52", "58", "64", "72", "80"};
		sizeBox = new JComboBox(sizes);
		sizeBox.setEditable(true);
		sizeBox.addActionListener(this);
		add(sizeBox);
		
		boldBtn = new JToggleButton(new ImageIcon(Presenter.class.getResource("/res/sm/format-text-bold.png")));
		boldBtn.setToolTipText("Bold");
		boldBtn.addActionListener(this);
		add(boldBtn);
		italicBtn = new JToggleButton(new ImageIcon(Presenter.class.getResource("/res/sm/format-text-italic.png")));
		italicBtn.setToolTipText("Italic");
		italicBtn.addActionListener(this);
		add(italicBtn);
//		underlineBtn = new JToggleButton(new ImageIcon(Presenter.class.getResource("/res/med/format-text-underline.png")));
//		underlineBtn.addActionListener(this);
//		add(underlineBtn);
		
		// set default font
		selectedFont = new Font(fontNames[0], Font.PLAIN, 6);
		setSelectedFontSize("20");
	}
	
	public void actionPerformed(ActionEvent e) {
		Object src = e.getSource();
		
		if (src == boldBtn || src == italicBtn) {
			int newStyle = Font.PLAIN;
			if (boldBtn.isSelected())
				newStyle += Font.BOLD;
			if (italicBtn.isSelected())
				newStyle += Font.ITALIC;
			
			selectedFont = selectedFont.deriveFont(newStyle);
//			checkUnderline();
		}
//		else if (src == underlineBtn) {
//			checkUnderline();
//		}
		else if (src == sizeBox) {
			try {
				float newSize = Float.parseFloat((String)sizeBox.getSelectedItem());
				selectedFont = selectedFont.deriveFont(newSize);
			} catch (NumberFormatException ex) {
				sizeBox.setSelectedItem(Integer.toString(selectedFont.getSize()));
			}
		}
		else if (src == fontBox) {
			selectedFont = new Font((String)fontBox.getSelectedItem(),
					selectedFont.getStyle(),
					selectedFont.getSize());
//			checkUnderline();
		}
		
		if (preview != null)
			preview.setFont(selectedFont);
	}
	
	@SuppressWarnings("unchecked")
//	private void checkUnderline() {
//		Map attributes = selectedFont.getAttributes();
//		if (underlineBtn.isSelected())
//			attributes.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
//		else
//			attributes.put(TextAttribute.UNDERLINE, new Integer(-1));
//		selectedFont = selectedFont.deriveFont(attributes);
//	}
	
	public static void main(String[] args) {
//		Font[] allfonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
//		ArrayList<Font> cjkFonts = new ArrayList<Font>();
//		
//		for (int j = 0; j < allfonts.length; j++) 
//		    if (allfonts[j].canDisplayUpTo("\u4e00") == -1)  
//		        cjkFonts.add(allfonts[j]);
		
		JFrame fr = new JFrame();
		FontChooser fc = new FontChooser();
		fr.add(fc);
		JLabel preview = new JLabel("Preview");
		fc.setPreview(preview);
		fr.add(preview, BorderLayout.SOUTH);
		fc.setSelectedFont("Arial");
		fc.setSelectedFontSize("40");
		fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		fr.pack();
		fr.setVisible(true);
	}

}
